package com.yanqu.road.server.manager.unioncampwar;

import com.yanqu.road.dao.impl.unioncampwar.UnionCampWarGroupDaoImpl;
import com.yanqu.road.dao.impl.unioncampwar.UnionCampWarGroupUnionDaoImpl;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.union.cross.CrossUnionInfo;
import com.yanqu.road.entity.union.cross.CrossUnionMember;
import com.yanqu.road.entity.union.cross.CrossUnionServerGroup;
import com.yanqu.road.entity.unioncampwar.UnionCampWarHoldData;
import com.yanqu.road.entity.unioncampwar.center.CenterUnionCampWarGroupData;
import com.yanqu.road.entity.unioncampwar.config.UnionCampWarBuffConfig;
import com.yanqu.road.entity.unioncampwar.cross.CrossUnionCampWarGroupData;
import com.yanqu.road.entity.unioncampwar.cross.CrossUnionCampWarGroupUnionData;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.config.unioncampwar.UnionCampWarHoldConfig;
import com.yanqu.road.logic.helper.MathHelper;
import com.yanqu.road.logic.helper.UnionActivityGroupHelper;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.server.TempCrossMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.config.CrossSystemLoopMgr;
import com.yanqu.road.server.manager.union.CrossUnionConfigMgr;
import com.yanqu.road.server.manager.union.CrossUnionMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.CrossUnionCampWarGroupMgr;
import com.yanqu.road.server.manger.CrossUnionServerGroupMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class CrossUnionCampWarLockGroupMgr extends TempCrossMgr {
    private static final Object lock = new Object();
    private static RandomHelper randomHelper = new RandomHelper();
    //centergroupId gorupId
    private static Map<Integer, Map<Integer, CrossUnionCampWarGroupData>> groupDataMap = new ConcurrentHashMap<>();
    /**
     * 分组时的周id
     */
    private static int groupWeekId;
    //报名期结束通过这个索引玩家的商会
    private static Map<Long, CrossUnionCampWarGroupUnionData> memberIdunionMap = new ConcurrentHashMap<>();

    @Override
    public boolean removeExpireData() throws Exception {
        return true;
    }

    @Override
    public boolean init() throws Exception {
        addUnionCampWarGroupMgrReloadListener();
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        getLogger().info("CrossUnionCampWarLockGroupMgr reloadData start");
        Map<Integer, CenterUnionCampWarGroupData> centerGroupMap = CrossUnionCampWarGroupMgr.getServerGroupMap();
        if (null == centerGroupMap || centerGroupMap.isEmpty()) {
            return true;
        }
        int weekId = GameConfig.getSystemThisWeekId();
        ArrayList<Integer> centerGroupIds = new ArrayList<>(centerGroupMap.keySet());
        Map<Integer, Map<Integer, CrossUnionCampWarGroupData>> dataMap = new UnionCampWarGroupDaoImpl().getCrossUnionCampWarGroupDataMap(centerGroupIds, weekId);


        boolean isRegistrationEnd = ConfigMgr.getUnionCampWarConfig().isRegistrationEndTime();
        Map<Long, CrossUnionCampWarGroupUnionData> tempMemberIdunionMap = new ConcurrentHashMap<>();
        Map<Integer, Map<Integer, List<CrossUnionCampWarGroupUnionData>>> groupUnionDataMap = new UnionCampWarGroupUnionDaoImpl().getCrossUnionCampWarGroupUnionDataMap(centerGroupIds, weekId);
        for (Map.Entry<Integer, Map<Integer, List<CrossUnionCampWarGroupUnionData>>> entry : groupUnionDataMap.entrySet()) {
            int centerGroupId = entry.getKey();
            if (!dataMap.containsKey(centerGroupId)){
                continue;
            }

            for (Map.Entry<Integer, List<CrossUnionCampWarGroupUnionData>> groupEntry : entry.getValue().entrySet()) {
                int groupId = groupEntry.getKey();
                if (!dataMap.get(centerGroupId).containsKey(groupId)){
                    continue;
                }

                CrossUnionCampWarGroupData groupData = dataMap.get(centerGroupId).get(groupId);
                for (CrossUnionCampWarGroupUnionData groupUnionData : groupEntry.getValue()) {
                    groupData.putUnionData(groupUnionData);

                    if (isRegistrationEnd) {
                        for (Long memberId : groupUnionData.getMermberPositionMap().keySet()) {
                            tempMemberIdunionMap.put(memberId, groupUnionData);
                        }
                    }
                }
            }
        }

        groupDataMap = dataMap;
        memberIdunionMap = tempMemberIdunionMap;

        checkGroupWeekId();

        checkGrouping();

        getLogger().info("CrossUnionCampWarLockGroupMgr reloadData end");
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save(){
        List<CrossUnionCampWarGroupData> needRemoveList = new ArrayList<>();
        int weekId = GameConfig.getSystemThisWeekId();
        int preWeekId = GameConfig.getSystemPreWeekId();

        for (Integer centerGroupId : groupDataMap.keySet()) {
            Map<Integer, CrossUnionCampWarGroupData> dataMap = groupDataMap.get(centerGroupId);
            for (CrossUnionCampWarGroupData groupData : dataMap.values()) {
                if (groupData.isInsertOption()) {
                    new UnionCampWarGroupDaoImpl().add(groupData);
                } else if (groupData.isUpdateOption()) {
                    new UnionCampWarGroupDaoImpl().update(groupData);
                }

                for (CrossUnionCampWarGroupUnionData groupUnionData : groupData.getUnionDataList()) {
                    if (groupUnionData.isInsertOption()) {
                        new UnionCampWarGroupUnionDaoImpl().add(groupUnionData);
                    } else if (groupUnionData.isUpdateOption()) {
                        new UnionCampWarGroupUnionDaoImpl().update(groupUnionData);
                    }
                }

                if (groupData.getWeekId() != weekId && groupData.getWeekId() != preWeekId) {
                    needRemoveList.add(groupData);
                }
            }
        }

        for (CrossUnionCampWarGroupData groupData : needRemoveList) {
            synchronized (groupDataMap) {
                if (groupDataMap.containsKey(groupData.getCenterGroupId())) {
                    Map<Integer, CrossUnionCampWarGroupData> dataMap = groupDataMap.get(groupData.getCenterGroupId());
                    if (dataMap == null) {
                        continue;
                    }
                    if (dataMap.containsKey(groupData.getGroupId())) {
                        dataMap.remove(groupData.getGroupId());
                    }
                    if (dataMap.isEmpty()) {
                        groupDataMap.remove(groupData.getCenterGroupId());
                    }
                }
            }
        }

        List<Long> checkUserId = new ArrayList<>();
        synchronized (memberIdunionMap) {
            checkUserId.addAll(memberIdunionMap.keySet());
        }

        for (Long userId : checkUserId) {
            CrossUnionCampWarGroupUnionData groupUnionData = memberIdunionMap.get(userId);
            if (groupUnionData == null) {
                continue;
            }
            if (groupUnionData.getWeekId() != weekId && groupUnionData.getWeekId() != preWeekId) {
                synchronized (memberIdunionMap) {
                    groupUnionData = memberIdunionMap.get(userId);
                    if (groupUnionData != null && groupUnionData.getWeekId() != weekId && groupUnionData.getWeekId() != preWeekId) {
                        memberIdunionMap.remove(userId);
                    }
                }
            }
        }

        return true;
    }

    public static void addUnionCampWarGroupMgrReloadListener(){
        CrossUnionCampWarGroupMgr.addReloadListener(() -> {
            checkGroupWeekId();
            getLogger().info("CrossUnionCampWarLockGroupMgr listener CrossUnionCampWarGroupMgr reload");
        });
    }

    public static void checkGroupWeekId(){
        int weekId = GameConfig.getSystemThisWeekId();
        boolean isGroupEnd = !groupDataMap.isEmpty();
        for (Map.Entry<Integer, Map<Integer, CrossUnionCampWarGroupData>> entry : groupDataMap.entrySet()) {
            int centerGroupId = entry.getKey();
            CenterUnionCampWarGroupData centerGroupData = CrossUnionCampWarGroupMgr.getServerGroup(centerGroupId);
            for (CrossUnionCampWarGroupData groupData : entry.getValue().values()) {
                if (centerGroupData != null) {
                    centerGroupData.addServerSet(groupData.getServerSet());
                    if (groupData.getWeekId() != weekId) {
                        isGroupEnd = false;
                    }
                }
            }
        }

        if (isGroupEnd) {
            groupWeekId = weekId;
        } else {
            groupWeekId = 0;
        }
    }


    private static List<CrossUnionInfo> getUnionList(CenterUnionCampWarGroupData groupData) {

        // 是否只要活跃商会
        boolean checkActive = groupData.isNeedActive();

        List<CrossUnionInfo> list = new ArrayList<>();
        HashSet<Long> serverIdSet = new HashSet<>(groupData.getServerSet());
        List<CrossUnionInfo> unionListByServerList = CrossUnionMgr.getUnionListByServerList(serverIdSet);
        for (CrossUnionInfo crossUnionInfo : unionListByServerList) {
            if (crossUnionInfo.isDelete()) {
                continue;
            }
            if (checkActive && CrossUnionConfigMgr.getUnionLv(crossUnionInfo.getExperience()) < 3) { // 活跃商会需要再判断等级大于等于3
                continue;
            }
            if (checkActive && !isActiveUnion(crossUnionInfo)) {
                continue;
            }
            list.add(crossUnionInfo);
        }
        return list;
    }

    private static boolean isActiveUnion(CrossUnionInfo crossUnionInfo) {
        Map<Long, CrossUnionMember> memberMap = CrossUnionMgr.getUnionMemberMap(crossUnionInfo.getUnionUid());
        if (memberMap != null) {
            long activeTime = System.currentTimeMillis() / 1000 - DateHelper.DAY_SECONDS * 7;
            for (CrossUnionMember member : memberMap.values()) {
                // 从member拿info
                UserBaseInfo info = member.getUserBaseInfo();
                if (info.getLastLoginTime() > activeTime) {
                    return true;
                }
                // 从CrossUserMgr随便拿info随便看看
                CrossUserBaseInfo baseInfo = CrossUserMgr.getMemUserBaseInfo(member.getUserId());
                if (baseInfo != null) {
                    if (baseInfo.getUserBaseInfo().getLastLoginTime() > activeTime) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static void checkGrouping() {
        if (!ConfigMgr.getUnionCampWarConfig().isInRegistrationTime()) {//报名期分组和分阵营
            return;
        }
        int thisWeekId = GameConfig.getSystemThisWeekId();
        if (thisWeekId == groupWeekId) {
            return;
        }

        List<ServerInfo> openServerList = new ArrayList<>();

        String systemLoop = ConfigHelper.getValue("systemLoop");
        if (StringUtils.isNullOrEmpty(systemLoop) || systemLoop.equals("1")) {
            openServerList = CrossSystemLoopMgr.getLoopServerList(eSystemId.UnionCampWar.getValue());
        } else {
            String testActivityServerId = ConfigHelper.getValue("testActivityServerId");
            if (!StringUtils.isNullOrEmpty(testActivityServerId)) {
                List<Long> serverIds = StringUtils.stringToLongList(testActivityServerId, ";");
                for (Long serverId : serverIds) {
                    openServerList.add(ServerListMgr.getServerInfo(serverId));
                }
            } else {
                openServerList = ServerListMgr.getOpenServerList(ConfigHelper.getInt("channelId"));
            }
        }

        if (openServerList.isEmpty()){ //没有区服分配,清空分配的区服
            groupWeekId = thisWeekId;
            Map<Integer, CenterUnionCampWarGroupData> serverGroupMap = CrossUnionCampWarGroupMgr.getServerGroupMap();
            if (serverGroupMap != null) {
                for (CenterUnionCampWarGroupData warGroupData : serverGroupMap.values()) {
                    warGroupData.setServerSet(new HashSet<>());
                }
            }
            return;
        }

        //根据开服天数要求取服务器
        Map<Integer, List<Long>> serverListMap = new HashMap<>();

        //分区服,从最大开服天数要求的开始遍历
        List<CenterUnionCampWarGroupData> serverGroupList = CrossUnionCampWarGroupMgr.getServerGroupList();
        Set<Long> includeServerIds = new HashSet<>();
        for (int i = serverGroupList.size(); i > 0; i--) {
            CenterUnionCampWarGroupData centerGroupData = serverGroupList.get(i - 1);
            Set<Long> serverIds = getServerIdsByOpenDays(openServerList, centerGroupData.getStartOpenDay(), centerGroupData.getEndOpenDay(), includeServerIds);
            serverListMap.put(centerGroupData.getGroupId(), new ArrayList<>(serverIds));
        }

        for (int i = 0; i < 5; i++) {
            //检查5次，把不满足最小区服数的区间往旁边区间合并
            if (checkBigGroupMap(serverListMap)) {
                break;
            }
        }

        for (Map.Entry<Integer, List<Long>> entry : serverListMap.entrySet()) {
            CenterUnionCampWarGroupData centerGroup = CrossUnionCampWarGroupMgr.getServerGroup(entry.getKey());
            if (centerGroup == null) {
                continue;
            }
            centerGroup.setServerSet(entry.getValue());
        }

        //分组分阵营
        for (CenterUnionCampWarGroupData centerGroupData : serverGroupList) {
            if (centerGroupData.getServerSet().isEmpty()) {
                continue;
            }
            if (!grouping(centerGroupData, thisWeekId)) {
                //分组失败,重置参与区服
                centerGroupData.setServerSet(new HashSet<>());
            }
        }

        groupWeekId = thisWeekId;
    }

    /**
     * 检查下大分组，不满足的区间需要合并
     */
    private static boolean checkBigGroupMap(Map<Integer, List<Long>> bigGroupMap) {
        // 找出不满足的区间
        List<Integer> needMergeRange = new ArrayList<>();
        for (Map.Entry<Integer, List<Long>> entry : bigGroupMap.entrySet()) {
            int groupId = entry.getKey();
            CenterUnionCampWarGroupData centerGroup = CrossUnionCampWarGroupMgr.getServerGroup(groupId);
            if (centerGroup == null) {
                continue;
            }
            if (entry.getValue().isEmpty()) {
                continue;
            }
            if (entry.getValue().size() < centerGroup.getMinServerNum()) {
                needMergeRange.add(entry.getKey());
            }
        }

        if (needMergeRange.isEmpty()) {
            return true;
        }
        // 处理不满足的区间
        for (Integer groupId : needMergeRange) {
            CenterUnionCampWarGroupData centerGroup = CrossUnionCampWarGroupMgr.getServerGroup(groupId);
            if (centerGroup == null) {
                continue;
            }
            List<Long> list = bigGroupMap.get(groupId);
            // 这边再校验一次，防止有中途插进来的
            if (list == null || list.size() >= centerGroup.getMinServerNum()) {
                continue;
            }
            // 找临近的区间最小的
            int minRange = findMinRange(groupId, bigGroupMap);
            if (!bigGroupMap.containsKey(minRange)) {
                // 没得找
                continue;
            }
            // 加到临近区间
            List<Long> list1 = bigGroupMap.getOrDefault(minRange, new ArrayList<>());
            list1.addAll(list);
            bigGroupMap.put(minRange, list1);

            //清除原来的
            bigGroupMap.get(groupId).clear();
        }

        return false;
    }

//    private static boolean checkBigGroupMapTest(Map<Integer, List<Long>> bigGroupMap) {
//        // 找出不满足的区间
//        int minNum = 3;
//        List<Integer> needMergeRange = new ArrayList<>();
//        for (Map.Entry<Integer, List<Long>> entry : bigGroupMap.entrySet()) {
//            int groupId = entry.getKey();
//            if (entry.getValue().isEmpty()) {
//                continue;
//            }
//            if (entry.getValue().size() < minNum) {
//                needMergeRange.add(entry.getKey());
//            }
//        }
//
//        if (needMergeRange.isEmpty()) {
//            return true;
//        }
//        // 处理不满足的区间
//        for (Integer groupId : needMergeRange) {
//            List<Long> list = bigGroupMap.get(groupId);
//            // 这边再校验一次，防止有中途插进来的
//            if (list == null || list.size() >= minNum) {
//                continue;
//            }
//            // 找临近的区间最小的
//            int minRange = findMinRange(groupId, bigGroupMap);
//            if (!bigGroupMap.containsKey(minRange)) {
//                // 没得找
//                continue;
//            }
//            // 加到临近区间
//            List<Long> list1 = bigGroupMap.getOrDefault(minRange, new ArrayList<>());
//            list1.addAll(list);
//            bigGroupMap.put(minRange, list1);
//
//            //清除原来的
//            bigGroupMap.get(groupId).clear();
//        }
//
//        return false;
//    }

    /**
     * 双指针查找直到找到满足的
     */
    public static int findMinRange(int groupId, Map<Integer, List<Long>> bigGroupMap) {
        if (groupId == -1) {
            return -1;
        }
        // 往左找
        int tempLeftIndex = groupId - 1;
        int leftCnt = 0;
        while (bigGroupMap.containsKey(tempLeftIndex)) {
            leftCnt = bigGroupMap.getOrDefault(tempLeftIndex, new ArrayList<>()).size();
            if (leftCnt > 0) {
                break;
            }
            tempLeftIndex--;
        }
        // 往右找
        int tempRightIndex = groupId + 1;
        int rightCnt = 0;
        while (bigGroupMap.containsKey(tempRightIndex)) {
            rightCnt = bigGroupMap.getOrDefault(tempRightIndex, new ArrayList<>()).size();
            if (rightCnt > 0) {
                break;
            }
            tempRightIndex++;
        }

        if (leftCnt == 0 && rightCnt == 0) {
            return -1;
        }
        if (leftCnt >= rightCnt) {
            if (rightCnt > 0) {
                return tempRightIndex;
            } else {
                return tempLeftIndex;
            }
        }else {
            if (leftCnt > 0) {
                return tempLeftIndex;
            } else {
                return tempRightIndex;
            }
        }
    }

    public static List<CrossUnionCampWarGroupData> getWarGroupList(CenterUnionCampWarGroupData centerGroupData) {
        List<CrossUnionCampWarGroupData> list = new ArrayList<>();
        Map<Integer, CrossUnionCampWarGroupData> dataMap = groupDataMap.get(centerGroupData.getGroupId());
        if (null == dataMap) {
            return list;
        }
        list.addAll(dataMap.values());
        return list;
    }

    /**
     * 分阵营
     */
    public static void campGrouping(CenterUnionCampWarGroupData centerGroupData, int weekId) {
        List<CrossUnionCampWarGroupData> warGroupList = getWarGroupList(centerGroupData);
        for (CrossUnionCampWarGroupData groupData : warGroupList) {
            List<CrossUnionInfo> unionInfoList = new ArrayList<>();
            for (CrossUnionCampWarGroupUnionData groupUnionData : groupData.getUnionMap().values()) {
                CrossUnionInfo unionInfo = CrossUnionMgr.getUnionInfo(groupUnionData.getUnionId());
                if (null == unionInfo) {
                    groupUnionData.resetCamp();
                    continue;
                }
                if (unionInfo.isDelete()) {
                    groupUnionData.resetCamp();
                    continue;
                }

                unionInfoList.add(unionInfo);
            }
            Map<Integer, List<CrossUnionInfo>> campUnionListMap = devideIntoCamp(unionInfoList);
            for (Map.Entry<Integer, List<CrossUnionInfo>> entry : campUnionListMap.entrySet()) {
                int campId = entry.getKey();
                for (CrossUnionInfo unionInfo : entry.getValue()) {
                    CrossUnionCampWarGroupUnionData groupUnionData = groupData.getGroupUnionData(unionInfo.getUnionUid());
                    if (null == groupUnionData) {
                        continue;
                    }
                    groupUnionData.setCampId(campId);
                    groupUnionData.setWeekId(weekId);
                    groupUnionData.setTotalAbility(unionInfo.getTotalMaxAbility());
                }
            }
        }

    }

    private static Set<Long> getServerIdsByOpenDays(List<ServerInfo> serverInfos, int startDay, int endDay, Set<Long> includeServerIds) {
        Set<Long> serverIds = new HashSet<>();
        for (ServerInfo serverInfo : serverInfos) {
            if (includeServerIds.contains(serverInfo.getServerId())) {
                continue;
            }
            if (!ServerListMgr.isServerOpen(serverInfo)) {
                continue;
            }

            int serverOpenDay = ServerListMgr.getServerOpenDay(serverInfo);

            if (serverOpenDay >= startDay && serverOpenDay <= endDay) {
                CrossUnionServerGroup unionServerGroup = CrossUnionServerGroupMgr.getServerGroupByServerId(serverInfo.getServerId());
                if (unionServerGroup != null) {
                    serverIds.addAll(unionServerGroup.getServerList());
                    includeServerIds.addAll(unionServerGroup.getServerList());
                } else {
                    serverIds.add(serverInfo.getServerId());
                    includeServerIds.add(serverInfo.getServerId());
                }
            }
        }
        return serverIds;
    }

    /**
     * 分组
     */
    private static boolean grouping(CenterUnionCampWarGroupData groupData, int weekId) {
        synchronized (lock) {
            // 获取可选商会
            List<CrossUnionInfo> unionList = getUnionList(groupData);

            int minGroupNum = unionList.size() / (ConfigMgr.getUnionCampWarConfig().getTopUnionCount() * 2);
            if (minGroupNum == 0) {//活跃的总商会都不够一组，按所有商会来取
                groupData.setNeedActive(false);
                unionList = getUnionList(groupData);
                minGroupNum = unionList.size() / (ConfigMgr.getUnionCampWarConfig().getTopUnionCount() * 2);
                if (minGroupNum == 0) {//总商会都不够一组,不开了
                    getLogger().error("商帮商会数不够一组,不开了,{},{}", groupData.getGroupId(), groupData.getStartOpenDay());
                    return false;
                }
            }

            // 分组参数
            int groupNum = 1; // 分几组
            int unionNum = 1000; // 每组多少个商会
            boolean needGroup = groupData.getGroupPerNum() > 0;
            if (needGroup) {
                groupNum = groupData.getServerSet().size() / groupData.getGroupPerNum();
                if (groupNum == 0) {
                    groupNum = 1;
                }
                unionNum = groupData.getUnionNum();
            }

            if (groupNum > minGroupNum) {//极端情况,取到的总的活跃商会都不够区服分的组数
                groupNum = minGroupNum;
                unionNum = unionList.size();
            }

            // 取前N名参与
            unionList = unionList.stream().sorted(Comparator.comparing(CrossUnionInfo::getTotalMaxAbility).reversed()).limit(groupNum * unionNum).collect(Collectors.toList());

            // 多次分组取最佳结果
            List<List<CrossUnionInfo>> bestRandomGroupResult = getBestRandomGroupResult(groupData, unionList, groupNum, 10);

            // 分组
            Map<Integer, Map<Integer, List<CrossUnionInfo>>> listMap = new HashMap<>();
            int tempGroupId = needGroup ? UnionActivityGroupHelper.NEED_GROUP_FIRST_ID : UnionActivityGroupHelper.NO_NEED_GROUP_ID;
            for (List<CrossUnionInfo> list : bestRandomGroupResult) {
                //再分阵营
//                Map<Integer, List<CrossUnionInfo>> campUnionListMap = devideIntoCamp(list);
                Map<Integer, List<CrossUnionInfo>> campUnionListMap = devideIntoCamp2(list);
                listMap.put(tempGroupId++, campUnionListMap);
            }

            // 生成数据
            Map<Integer, CrossUnionCampWarGroupData> groupMap = new ConcurrentHashMap<>();
            for (Map.Entry<Integer, Map<Integer, List<CrossUnionInfo>>> entry : listMap.entrySet()) {
                int groupId = entry.getKey();

                ConcurrentHashMap<String, CrossUnionCampWarGroupUnionData> map = new ConcurrentHashMap<>();
                for (Map.Entry<Integer, List<CrossUnionInfo>> campEntry : entry.getValue().entrySet()) {
                    int campId = campEntry.getKey();
                    for (CrossUnionInfo crossUnionInfo : campEntry.getValue()) {
                        map.put(crossUnionInfo.getUnionUid(), createCrossGroupData(groupData.getGroupId(), groupId, campId, weekId, crossUnionInfo));
                    }
                }

                CrossUnionCampWarGroupData group = new CrossUnionCampWarGroupData();
                group.setCenterGroupId(groupData.getGroupId());
                group.setGroupId(groupId);
                group.setWeekId(weekId);
                group.setServerSet(calcServerIdSet(groupData, map));
                group.setUnionMap(map);
                group.setInsertOption();

                groupMap.put(group.getGroupId(), group);
            }

            putGroupMap(groupData.getGroupId(), groupMap);
        }

        return true;
    }

    /**
     * 分阵营,这个是按两边数量平均来分
     */
    private static Map<Integer, List<CrossUnionInfo>> devideIntoCamp(List<CrossUnionInfo> unionInfoList) {
        int campNeed = 2;
        int campUnionNum = BigDecimal.valueOf(unionInfoList.size())
                .divide(BigDecimal.valueOf(campNeed), 0, BigDecimal.ROUND_UP).intValue();
        unionInfoList = unionInfoList.stream().sorted(Comparator.comparing(CrossUnionInfo::getTotalMaxAbility).reversed()).collect(Collectors.toList());

        Map<Integer, List<CrossUnionInfo>> campMap = new ConcurrentHashMap<>();
        Map<Integer, BigInteger> campAbilityMap = new ConcurrentHashMap<>();
        for (int i = 1; i <= campNeed; i++) {
            campMap.put(i, new ArrayList<>());
            campAbilityMap.put(i, BigInteger.ZERO);
        }

        BigInteger minAbility = BigInteger.ZERO;
        for (int r = 0; r < unionInfoList.size(); r++) {
            CrossUnionInfo unionInfo = unionInfoList.get(r);
            int minGruop = 1;
            for (Map.Entry<Integer, BigInteger> entry : campAbilityMap.entrySet()) {
                // 跳过已经分配满的阵营
                if (campMap.get(entry.getKey()).size() >= campUnionNum) {
                    continue;
                }
                if (entry.getValue().equals(BigInteger.ZERO)) {
                    minGruop = entry.getKey();
                    break;
                }
                if (minAbility.equals(BigInteger.ZERO)) {
                    minGruop = entry.getKey();
                    minAbility = entry.getValue();
                    continue;
                }

                // 取总赚钱最小的阵营（赚钱相同时，随机一下，避免一直一样）
                if (entry.getValue().compareTo(minAbility) < 0 ||
                        entry.getValue().equals(minAbility) && randomHelper.next(2) == 0) {
                    minGruop = entry.getKey();
                    minAbility = entry.getValue();
                }
            }

            campMap.get(minGruop).add(unionInfo);
            campAbilityMap.put(minGruop, campAbilityMap.get(minGruop).add(unionInfo.getTotalMaxAbility()));
        }

        return campMap;
    }

    /**
     * 分阵营,只按赚钱,不管数量
     */
    private static Map<Integer, List<CrossUnionInfo>> devideIntoCamp2(List<CrossUnionInfo> unionInfoList) {
        int campNeed = 2;

        unionInfoList = unionInfoList.stream().sorted(Comparator.comparing(CrossUnionInfo::getTotalMaxAbility).reversed()).collect(Collectors.toList());

        Map<Integer, List<CrossUnionInfo>> campMap = new ConcurrentHashMap<>();
        Map<Integer, BigInteger> campAbilityMap = new ConcurrentHashMap<>();
        for (int i = 1; i <= campNeed; i++) {
            campMap.put(i, new ArrayList<>());
            campAbilityMap.put(i, BigInteger.ZERO);
        }


        for (int r = 0; r < unionInfoList.size(); r++) {
            CrossUnionInfo unionInfo = unionInfoList.get(r);
            int minGruop = 1;
            BigInteger minAbility = BigInteger.ZERO;
            for (Map.Entry<Integer, BigInteger> entry : campAbilityMap.entrySet()) {
                if (entry.getValue().equals(BigInteger.ZERO)) {
                    minGruop = entry.getKey();
                    break;
                }
                if (minAbility.equals(BigInteger.ZERO)) {
                    minGruop = entry.getKey();
                    minAbility = entry.getValue();
                    continue;
                }

                // 取总赚钱最小的阵营（赚钱相同时，随机一下，避免一直一样）
                if (entry.getValue().compareTo(minAbility) < 0 ||
                        entry.getValue().equals(minAbility) && randomHelper.next(2) == 0) {
                    minGruop = entry.getKey();
                    minAbility = entry.getValue();
                }
            }

            campMap.get(minGruop).add(unionInfo);
            campAbilityMap.put(minGruop, campAbilityMap.get(minGruop).add(unionInfo.getTotalMaxAbility()));
        }

        // 检查是否有阵营不够数量,如果有阵营不够数量,并且两外一个阵营有多余的,则从多余的阵营中取多出来的商会进行补充
        int minNeed = ConfigMgr.getUnionCampWarConfig().getTopUnionCount();
        List<CrossUnionInfo> outList = new ArrayList<>();
        int needAddCampId = 0;
        List<CrossUnionInfo> changeList = new ArrayList<>();
        for (Map.Entry<Integer, List<CrossUnionInfo>> entry : campMap.entrySet()) {
            int campId = entry.getKey();
            if (entry.getValue().size() > minNeed) {
                changeList = entry.getValue();
                if (outList.isEmpty()) {
                    for (int i = minNeed; i < changeList.size(); i++) {
                        outList.add(changeList.get(i));
                    }
                } else {
                    break;
                }
            } else {
                needAddCampId = campId;
            }
        }

        if (needAddCampId != 0 && !outList.isEmpty()) {
            List<CrossUnionInfo> needAddList = campMap.get(needAddCampId);
            int needAddNum = minNeed - needAddList.size();
            for (int i = 0; i < needAddNum && i < outList.size(); i++) {
                //outList倒序遍历
                CrossUnionInfo unionInfo = outList.get(outList.size() - 1 - i);
                needAddList.add(unionInfo);
                changeList.remove(unionInfo);
            }
        }

        return campMap;
    }

    /**
     * 尝试多次随机分组，取最佳分组结果
     *
     * @param tryTimes 怕死少来几次
     */
    private static List<List<CrossUnionInfo>> getBestRandomGroupResult(CenterUnionCampWarGroupData groupData, List<CrossUnionInfo> unionInfoList, int groupNum, int tryTimes) {
        // 无需分组直接返回
        if (groupNum <= 1 || unionInfoList.isEmpty()) {
            List<List<CrossUnionInfo>> listList = new ArrayList<>();
            listList.add(unionInfoList);
            return listList;
        }

        List<List<CrossUnionInfo>> bestListList = null;
        BigDecimal bestValue = null;
        for (int i = 0; i < tryTimes; i++) {
            // 打乱
            ArrayList<CrossUnionInfo> randomUnionList = new ArrayList<>(unionInfoList);
            Collections.shuffle(randomUnionList);
            // 生成数据
            List<List<CrossUnionInfo>> groupUnionList = new ArrayList<>();
            for (int j = 0; j < groupNum; j++) {
                groupUnionList.add(new ArrayList<>());
            }
            for (int j = 0; j < randomUnionList.size(); j++) {
                groupUnionList.get(j % groupNum).add(randomUnionList.get(j));
            }
            // 拿赚速计算方差
            List<BigInteger> earnSpeedList = new ArrayList<>();
            for (List<CrossUnionInfo> unionList : groupUnionList) {
                BigInteger groupEarnSpeed = BigInteger.ZERO;
                for (CrossUnionInfo unionInfo : unionList) {
                    groupEarnSpeed = groupEarnSpeed.add(unionInfo.getTotalMaxAbility());
                }
                earnSpeedList.add(groupEarnSpeed);
            }
            BigDecimal variance = MathHelper.calcVariance(earnSpeedList);
            // 比较最佳结果
            if (bestListList == null || variance.compareTo(bestValue) < 0) {
                bestListList = groupUnionList;
                bestValue = variance;
            }

            try {
                for (int j = 0; j < groupUnionList.size(); j++) {
                    List<CrossUnionInfo> list = groupUnionList.get(j);
                    for (int k = 0; k < list.size(); k++) {
                        CrossUnionInfo unionInfo = list.get(k);
                        getLogger().debug("配置组id\t{}\t分组次数\t{}\t组\t{}\t商会\t{}\t赚钱\t{}",
                                groupData.getGroupId(), (i + 1), j, unionInfo.getUnionUid(), unionInfo.getTotalMaxAbility().toString()
                        );
                    }
                }
                getLogger().debug("配置组id\t{}\t分组次数\t{}\t方差\t{}\t------------------------------",
                        groupData.getGroupId(), (i + 1), variance.toString()
                );
            } catch (Exception e) {
                getLogger().error("pring log error... : ", e);
            }
        }

        return bestListList;
    }

    private static CrossUnionCampWarGroupUnionData createCrossGroupData(int centerGroupId, int groupId, int campId, int weekId, CrossUnionInfo crossUnionInfo) {
        Map<Long, Integer> memberPositionMap = CrossUnionMgr.getMemberPositionMap(crossUnionInfo.getUnionUid());

        CrossUnionCampWarGroupUnionData groupData = new CrossUnionCampWarGroupUnionData();
        groupData.setCenterGroupId(centerGroupId);
        groupData.setGroupId(groupId);
        groupData.setCampId(campId);
        groupData.setWeekId(weekId);
        groupData.setTotalAbility(crossUnionInfo.getTotalMaxAbility());
        groupData.setUnionId(crossUnionInfo.getUnionUid());
        groupData.setServerId(crossUnionInfo.getServerId());
        groupData.setMermberPositionMap(memberPositionMap);
        groupData.setInsertOption();
        return groupData;
    }

    /**
     * 计算分组涉及的区服
     */
    private static Set<Long> calcServerIdSet(CenterUnionCampWarGroupData groupData, Map<String, CrossUnionCampWarGroupUnionData> map) {

        // 无需分组活动的区服全部涉及
        if (groupData.getGroupPerNum() == 0) {
            return new HashSet<>(groupData.getServerSet());
        }

        // 拿活动分组内，商会对应的商会分组
        Set<Integer> unionGroupIdSet = new HashSet<>();
        for (CrossUnionCampWarGroupUnionData union : map.values()) {
            int unionGroupId = CrossUnionServerGroupMgr.getGroupIdByServerId(union.getServerId());
            unionGroupIdSet.add(unionGroupId);
        }
        // 拿分组内的区服
        Set<Long> serverIdSet = new HashSet<>();
        for (int unionGroupId : unionGroupIdSet) {
            serverIdSet.addAll(CrossUnionServerGroupMgr.getGroupServer(unionGroupId));
        }
        return serverIdSet;
    }

    public static void putGroupMap(int centerGroupId, Map<Integer, CrossUnionCampWarGroupData> groupMap) {
        groupDataMap.put(centerGroupId, groupMap);
        getLogger().debug("后台分组id {} 添加分组数据， 一共 {} 组。", centerGroupId, groupMap.size());
    }

    public static CrossUnionCampWarGroupUnionData getUnionData(int centerGroupId, String unionUid) {
        Map<Integer, CrossUnionCampWarGroupData> campWarGroupDataMap = groupDataMap.get(centerGroupId);
        if (campWarGroupDataMap != null) {
            for (CrossUnionCampWarGroupData group : campWarGroupDataMap.values()) {
                if (group.getUnionMap().containsKey(unionUid)){
                    return group.getUnionMap().get(unionUid);
                }
            }
        }
        return null;
    }

    public static CrossUnionCampWarGroupUnionData getUnionData(long serverId, String unionUid) {
        int centerGroupId = CrossUnionCampWarGroupMgr.getGroupIdByServerId(serverId);
        return getUnionData(centerGroupId, unionUid);
    }

    public static int getGroupId(int centerGroupId, String unionUid) {
        CrossUnionCampWarGroupUnionData unionData = getUnionData(centerGroupId, unionUid);
        if (unionData != null) {
            return unionData.getGroupId();
        }
        return UnionActivityGroupHelper.NO_GROUP_ID;
    }

    public static int getGroupId(long serverId, String unionUid) {
        CrossUnionCampWarGroupUnionData unionData = getUnionData(serverId, unionUid);
        if (unionData != null) {
            return unionData.getGroupId();
        }
        return UnionActivityGroupHelper.NO_GROUP_ID;
    }

    public static int getCampId(long serverId, String unionUid) {
        CrossUnionCampWarGroupUnionData unionData = getUnionData(serverId, unionUid);
        if (null != unionData) {
            return unionData.getCampId();
        }
        return 0;
    }

    public static int getCampId(int centerGroupId, String unionUid) {
        CrossUnionCampWarGroupUnionData unionData = getUnionData(centerGroupId, unionUid);
        if (null != unionData) {
            return unionData.getCampId();
        }
        return 0;
    }

    public static CrossUnionCampWarGroupData getGroupData(long serverId, String unionId) {
        int centerGroupId = CrossUnionCampWarGroupMgr.getGroupIdByServerId(serverId);
        int groupId = getGroupId(centerGroupId, unionId);
        return getGroupData(centerGroupId, groupId);
    }

    public static CrossUnionCampWarGroupData getGroupData(int centerGroupId, int groupId) {
        if (!groupDataMap.containsKey(centerGroupId)) {
            return null;
        }
        return groupDataMap.get(centerGroupId).get(groupId);
    }

    public static List<RankProto.UnionRankTempMsg> getCampUnionRankMsgList(int centerGroupId, int groupId, int campId) {
        List<RankProto.UnionRankTempMsg> rankTempMsgList = new ArrayList<>();
        Map<Integer, CrossUnionCampWarGroupData> centerGroupDataMap = groupDataMap.get(centerGroupId);
        if (null == centerGroupDataMap) {
            return rankTempMsgList;
        }

        CrossUnionCampWarGroupData groupData = getGroupData(centerGroupId, groupId);
        if (null == groupData) {
            return rankTempMsgList;
        }

        List<CrossUnionInfo> unionInfoList = new ArrayList<>();

        for (CrossUnionCampWarGroupUnionData groupUnionData : groupData.getUnionMap().values()) {
            CrossUnionInfo unionInfo = CrossUnionMgr.getUnionInfo(groupUnionData.getUnionId());
            if (null == unionInfo) {
                continue;
            }
            if (unionInfo.isDelete()) {
                continue;
            }
            if (groupUnionData.getCampId() != campId) {
                continue;
            }

            unionInfoList.add(unionInfo);
        }

        unionInfoList.sort((o1, o2) -> {
            return o2.getTotalMaxAbility().compareTo(o1.getTotalMaxAbility());
        });


        for (int i = 0; i < unionInfoList.size(); i++) {
            CrossUnionInfo unionInfo = unionInfoList.get(i);
            RankProto.UnionRankTempMsg.Builder tempMsg = RankProto.UnionRankTempMsg.newBuilder();
            tempMsg.setUnionBaseData(UnionBasePb.parseUnionBaseTempMsg(CrossUnionMgr.parseUnionBaseInfo(unionInfo)));
            tempMsg.setUnionUid(unionInfo.getUnionUid());
            tempMsg.setValue(unionInfo.getTotalMaxAbility().toString());

            rankTempMsgList.add(tempMsg.build());
        }

        return rankTempMsgList;
    }

    public static Map<Integer, CrossUnionCampWarGroupData> getGroupDataMap(int centerGroupId) {
        return groupDataMap.get(centerGroupId);
    }

    public static void broadcastServerMsg(int centerGroupId, int groupId, YanQuMessage yqMsg) {
        CrossUnionCampWarGroupData groupData = getGroupData(centerGroupId, groupId);
        if (null == groupData) {
            return;
        }
        for (Long serverId : groupData.getServerSet()) {
            MessageHelper.sendPacket(serverId, 0, yqMsg);
        }
    }

    public static void putGroupUnionData(long userId, CrossUnionCampWarGroupUnionData groupUnionData) {
        synchronized (memberIdunionMap) {
            memberIdunionMap.put(userId, groupUnionData);
        }
    }

    public static CrossUnionCampWarGroupUnionData getGroupUnionData(long userId) {
        CrossUnionCampWarGroupUnionData groupUnionData = memberIdunionMap.get(userId);
        if (null != groupUnionData) {
            if (!groupUnionData.getMermberPositionMap().containsKey(userId)) {
                synchronized (memberIdunionMap) {
                    memberIdunionMap.remove(userId);
                }
                return null;
            }
        }
        return groupUnionData;
    }

    /**
     * 计算据点血量配置
     */
    public static void calcHoldHpConfig(UnionCampWarActivity warActivity) {
        getLogger().info("开始计算据点血量配置");
        CrossUnionCampWarGroupData groupData = getGroupData(warActivity.getCenterGroupId(), warActivity.getGroupId());
        if (groupData == null) {
            return;
        }
        List<Integer> hpParams1 = ConfigMgr.getUnionCampWarConfig().getHpParams1();
        List<Integer> hpParams2 = ConfigMgr.getUnionCampWarConfig().getHpParams2();
        List<List<Integer>> hpParams3 = ConfigMgr.getUnionCampWarConfig().getHpParams3();
        List<Integer> hpParams4 = ConfigMgr.getUnionCampWarConfig().getHpParams4();

        List<BigDecimal> memberAbilityList = new ArrayList<>();
        /**
         * 	1、取所有参与区服7日内活跃人数的赚钱值
         *
         * 		按总赚钱值从大到小排序，按排名将玩家分为3部分，算出3部分的赚钱平均值
         * 		（档位分界线取配置）
         * 		档位	总门客赚钱平均值	排名前n%
         * （档位1是最强档位）		1	动态计算	n1=10%
         * 		2	动态计算	n2=50%
         * 		3	动态计算	n3=100%
         *
         */
        //1、取所有参与区服7日内活跃人数的赚钱值
        //按总赚钱值从大到小排序，按排名将玩家分为3部分，算出3部分的赚钱平均值
        List<BigDecimal> avgMemberAbilityList = new ArrayList<>(); //每个挡位的玩家赚钱平均值,要入库
        List<BigDecimal> avgMemberNumList = new ArrayList<>(); //每个挡位的玩家数
        long nextDayZeroTime = DateHelper.getTodayZeroTimeStamp() / 1000 + DateHelper.DAY_SECONDS;
        for (CrossUnionCampWarGroupUnionData groupUnionData : groupData.getUnionDataList()) {
            for (Long memberId : groupUnionData.getMermberPositionMap().keySet()) {
                CrossUnionMember member = CrossUnionMgr.getUnionMemberByUserId(memberId);
                if (member == null) {
                    continue;
                }

                long lastLoginTime = member.getUserBaseInfo().getLastLoginTime();
                long days = (nextDayZeroTime - lastLoginTime) / DateHelper.DAY_SECONDS;
                if (days > 7) {//取7日活跃
                    continue;
                }
                memberAbilityList.add(new BigDecimal(member.getHistoryMaxAbility().toString()));
                getLogger().debug("商帮参与计算的玩家赚钱memberId={},memberAbility={}", memberId, member.getHistoryMaxAbility().toString());
            }
        }

        memberAbilityList.sort((o1, o2) -> {
            return o2.compareTo(o1);
        });
        int memberSize = memberAbilityList.size();
        getLogger().debug("商帮参与玩家数memberNum={}", memberSize);
        int startIdex = 0;
        for (Integer param : hpParams1) {
            int endIdx = memberSize * param / 1000;
            BigDecimal totalAbility = BigDecimal.ZERO;
            BigDecimal avgAbility = BigDecimal.ZERO;
            int num = 0;
            for (int i = startIdex; i < memberAbilityList.size() && i < endIdx; i++) {
                totalAbility = totalAbility.add(memberAbilityList.get(i));
                num++;
            }

            if (num > 0 && totalAbility.compareTo(BigDecimal.ZERO) > 0) {
                avgAbility = totalAbility.divide(BigDecimal.valueOf(num), 0, BigDecimal.ROUND_HALF_UP);
            }
            getLogger().debug("商帮参与玩家排名范围startRank={},endRank={},totalAbility={}", startIdex + 1, endIdx, totalAbility.toString());
            getLogger().debug("商帮参与玩家排名范围startRank={},endRank={},num={}", startIdex + 1, endIdx, num);
            getLogger().debug("商帮参与玩家排名范围startRank={},endRank={},avgAbility={}", startIdex + 1, endIdx, avgAbility.toString());
            avgMemberAbilityList.add(avgAbility);
            avgMemberNumList.add(BigDecimal.valueOf(num));

            startIdex = endIdx;
        }

        /**
         * 2、取据点参考防守商会
         *
         * 	据点类型	商会总门客赚钱参考值	商会总门客数参考值	取值方法
         * 	1	动态计算	动态计算	两边阵营第1商会平均值
         * 	2	动态计算	动态计算	两边阵营2~4名商会平均值
         * 	3	动态计算	动态计算	两边阵营5~10名商会平均值
         */

        Map<Integer, List<UnionCampWarHoldData>> holdDataListMap = warActivity.getHoldDataListMap();
        for (Map.Entry<Integer, List<UnionCampWarHoldData>> entry : holdDataListMap.entrySet()) {
            //按照id排序
            entry.getValue().sort((o1, o2) -> {
                return Integer.compare(o1.getHoldId(), o2.getHoldId());
            });
        }

        List<BigDecimal> avgUnionAbilityList = new ArrayList<>();
        List<BigDecimal> avgPatronsNumList = new ArrayList<>();

        for (UnionCampWarHoldConfig holdConfig : ConfigMgr.getUnionCampWarConfig().getHoldConfigList()) {
            BigDecimal totalAbility = BigDecimal.ZERO;
            BigDecimal patronsNum = BigDecimal.ZERO;
            int unionNum = 0;
            for (Map.Entry<Integer, List<UnionCampWarHoldData>> entry : holdDataListMap.entrySet()) {
                //取entry.getValue中指定范围为holdConfig的getStartHoldId到getEndHoldId的商会
                int startIdx = holdConfig.getStartHoldId() - 1;
                if (startIdx < 0) {
                    startIdx = 0;
                }
                if (startIdx > entry.getValue().size()) {
                    startIdx = entry.getValue().size() - 1;
                }
                int endIdx = holdConfig.getEndHoldId();
                if (endIdx > entry.getValue().size()) {
                    endIdx = entry.getValue().size();
                }
                List<UnionCampWarHoldData> list = entry.getValue().subList(startIdx, endIdx);
                for (UnionCampWarHoldData holdData : list) {
                    CrossUnionCampWarGroupUnionData groupUnionData = groupData.getGroupUnionData(holdData.getUnionId());
                    if (groupUnionData == null) {
                        continue;
                    }
                    totalAbility = totalAbility.add(new BigDecimal(groupUnionData.getTotalAbility().toString()));
                    getLogger().debug("商帮参与计算的商会赚钱,startRank={},endRank={},ability={}", startIdx + 1, endIdx, groupUnionData.getTotalAbility().toString());
                    getLogger().debug("商帮参与计算的商会门客数,startRank={},endRank={},patronsNum={}", startIdx + 1, endIdx, holdData.getPatronsNum());
                    patronsNum = patronsNum.add(BigDecimal.valueOf(holdData.getPatronsNum()));
                    unionNum++;
                }
            }
            BigDecimal avgUnionAbility = totalAbility.divide(BigDecimal.valueOf(unionNum), 2, BigDecimal.ROUND_HALF_UP);
            avgUnionAbilityList.add(avgUnionAbility);
            BigDecimal avgPatronsNum = patronsNum.divide(BigDecimal.valueOf(unionNum), 2, BigDecimal.ROUND_HALF_UP);
            avgPatronsNumList.add(avgPatronsNum);

            getLogger().debug("商帮商会平均赚钱,totalAbility={},unionNum={},avgUnionAbility={}", totalAbility.toString(), unionNum, avgUnionAbility.toString());
            getLogger().debug("商帮门客数,patronsNum={},unionNum={},avgPatronsNum={}", patronsNum, unionNum, avgPatronsNum.toString());
        }

        /**
         * 3、计算参考扣血数
         * 		（根据1、2结果，动态计算连胜数）
         * 	公式：
         * 		据点商会总门客赚钱参考值 / 据点商会总门客数参考值 = 防守商会门客平均赚钱
         * 		档位玩家总门客赚钱平均值 * 出战系数 / 防守商会门客平均赚钱 = 连胜数
         *
         * 	动态计算扣血数：A = ATT ( 出战系数1连胜数 ) + ATT（ 出战系数2连胜数 ) +……+ ATT（ 出战系数6连胜数 )
         *
         * 	扣血数	玩家档位
         * 	据点类型	1	2	3
         * 	1	A11	A21	A31
         * 	2	A12	A22	A32
         * 	3	A13	A23	A33
         *
         * 	4、血量分配
         * 		根据配置的玩家系数和连胜扣血，计算血量
         *
         * 	玩家系数配置	玩家档位
         * 	据点	1	2	3
         * 	1	f11	f21	f31
         * 	2	f12	f22	f32
         * 	3	f13	f23	f33
         *
         * 	公式：	玩家档位
         * 	据点	1	2	3
         * 	1	Z1=两个阵营档位1玩家总数量  * f11 * A11	Z2=两个阵营档位2玩家总数量  * f21 * A21	Z3=两个阵营档位3玩家总数量  * f31 * A31
         * 	2	Z1=两个阵营档位1玩家总数量  * f12 * A12	Z2=两个阵营档位2玩家总数量  * f22 * A22	Z3=两个阵营档位3玩家总数量  * f32 * A32
         * 	3	Z1=两个阵营档位1玩家总数量  * f13 * A13	Z2=两个阵营档位2玩家总数量  * f23 * A23	Z3=两个阵营档位3玩家总数量  * f33 * A33
         *
         *
         * 	最终据点血量 = （Z1 + Z2 +Z3）* X
         *
         * 		X根据据点不同而不同，走配置
         */
        for (int i = 0; i < ConfigMgr.getUnionCampWarConfig().getHoldConfigList().size(); i++) {
            UnionCampWarHoldConfig holdConfig = ConfigMgr.getUnionCampWarConfig().getHoldConfigList().get(i);
            BigDecimal avgUnionAbility = avgUnionAbilityList.get(i);
            BigDecimal avgPatronsNum = avgPatronsNumList.get(i);
            BigDecimal totalValueZ = BigDecimal.ZERO;

            for (int j = 0; j < avgMemberAbilityList.size(); j++) {
                BigDecimal avgMemberAbility = avgMemberAbilityList.get(j);
                BigDecimal avgMemberNum = avgMemberNumList.get(j);
                //据点商会总门客赚钱参考值 / 据点商会总门客数参考值 = 防守商会门客平均赚钱
                BigDecimal defendAvgAbility = avgUnionAbility.divide(avgPatronsNum, 2, BigDecimal.ROUND_HALF_UP);
                getLogger().debug("据点档位={},玩家档位={},防守商会门客平均赚钱,avgUnionAbility={},avgPatronsNum={},defendAvgAbility={}", i + 1, j + 1, avgUnionAbility, avgPatronsNum, defendAvgAbility);
                int valueA = 0;//动态扣血数
                for (Integer param : hpParams2) {
                    //档位玩家总门客赚钱平均值 * 出战系数 / 防守商会门客平均赚钱 = 连胜数
                    int winNum = 0;
                    if (defendAvgAbility.compareTo(BigDecimal.ZERO) != 0) {
                        winNum = avgMemberAbility.multiply(BigDecimal.valueOf(param)).divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_HALF_UP).divide(defendAvgAbility, 0, BigDecimal.ROUND_UP).intValue();
                        getLogger().debug("连胜数winNum={},avgMemberAbility={},param={},defendAvgAbility={}", winNum, avgMemberAbility, param, defendAvgAbility);
                        if (winNum > avgPatronsNum.intValue()) {
                            winNum = avgPatronsNum.intValue();
                        }
                    }
                    //动态计算扣血数：A = ATT ( 出战系数1连胜数 ) + ATT（ 出战系数2连胜数 ) +……+ ATT（ 出战系数6连胜数 )
                    int combAttValue = ConfigMgr.getUnionCampWarConfig().getCombAttValue(winNum);
                    getLogger().debug("ATT={},param={},winNum={}", combAttValue, param, winNum);
                    valueA += combAttValue;
                }
                int valueF = hpParams3.get(i).get(j);

                BigDecimal valueZ = BigDecimal.valueOf(valueA).multiply(BigDecimal.valueOf(valueF).divide(BigDecimal.valueOf(1000))).multiply(avgMemberNum);
                getLogger().info("A={},F={},avgMemberNum={},Z={}", valueA, valueF, avgMemberNum, valueZ);
                totalValueZ = totalValueZ.add(valueZ);
            }

            int valueX = hpParams4.get(i);

            //最终据点血量 = （Z1 + Z2 +Z3）* X
            int finalHp = totalValueZ.multiply(BigDecimal.valueOf(valueX)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_HALF_UP).intValue();
            getLogger().info("档位={},z={},x={},最终据点血量={}", i + 1, totalValueZ, valueX, finalHp);
            for (int holdId = holdConfig.getStartHoldId(); holdId <= holdConfig.getEndHoldId(); holdId++) {
                for (UnionCampWarHoldData holdData : warActivity.getHoldDataList(holdId)) {
                    if (finalHp > holdData.getTotalHp()) {//要大于TITLE_SET的血量才设置
                        holdData.setLeftHp(finalHp);
                        holdData.setTotalHp(finalHp);
                    }
                }
            }
        }

        warActivity.getCampData().setAvgAbilityList(avgMemberAbilityList);

        for (UnionCampWarBuffConfig buffConfig : ConfigMgr.getUnionCampWarConfig().getBuffConfigMap().values()) {
            for (int i = 0; i < avgMemberAbilityList.size(); i++) {
                BigDecimal avgAbility = avgMemberAbilityList.get(i);
                BigInteger hpRevert = avgAbility.multiply(BigDecimal.valueOf(buffConfig.getRevertHpPer())).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
                getLogger().info("buffId={},param={},玩家档位={},avgAbility={},hpRevert={}", buffConfig.getBuffId(), buffConfig.getRevertHpPer(), i + 1, avgAbility, hpRevert);
            }
        }

    }

    /**
     * 热更专用
     */
    public static void hotFix() {

    }

}
